package com.ruoyi.aitklw.service;

import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.aitcommon.anotation.ServiceLog;
import com.ruoyi.aitcommon.service.IAitEntityInfoService;
import com.ruoyi.aitcommon.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;

/**
 * 凯路威项目
 * 调用PRP接口
 */
@Service
public class KLWPRPRestService {
    @Autowired
    IAitEntityInfoService infoService;
    @Autowired
    EntityCache entityCache;

    /**
     * 主子表转换为单表
     * @param docs 单据集合list
     * @param lineField 子表字段名称
     * @return 拉平的子表
     */
    @ServiceLog("主子表转换为单表")
    public List<Map<String,Object>> doc2List(List<Map<String,Object>> docs,String lineField) throws Exception {
        List<Map<String, Object>> retlist = new ArrayList<>();

        for (Map<String, Object> doc : docs) {
            //针对单据,每行处理
            if (!doc.containsKey(lineField))
                throw new Exception("doc中不存在字段[" + lineField + "]");
            Object lineValue = doc.get(lineField);
            if (!(lineValue instanceof List))
                throw new Exception("字段[" + lineField + "]类型不是集合");
            List lines = (List) lineValue;
            for (Object line : lines) {
                //针对单据行,每行
                if (!(line instanceof Map))
                    throw new Exception("字段[" + lineField + "]类型不是MAP集合");
                Map<String, Object> line1 = (Map<String, Object>) line;
                Map<String, Object> newline = new LinkedHashMap<>();

                for (String key1 : line1.keySet()) {
                    //增对子行 每行每列
                    Object value = line1.get(key1);
                    String key2 = lineField + "_" + key1;
                    newline.put(key2, value);
                }
                for (String key : doc.keySet()) {
                    //针对单据 每行每列
                    if (key.equals(lineField)) continue;
                    Object value = doc.get(key);
                    newline.put(key, value);
                }
                retlist.add(newline);
            }
        }
        return retlist;
    }

    /**
     * 调用凯路威PRP系统服务
     * @param url 调用地址
     * @param param 接口参数(clientId,accessKey,loginUser)
     * @param data 数据
     * @return PRP返回json,在外部解析
     */
    private JSONObject restInvoke(String url,Map<String,Object> param, Map<String,Object> data)
            throws Exception {
        ExceptionUtils.checkBlankOrUndefined(data,"没有data数据");

//      获取sign
        final Map<String, Object> head = this.getToken(param);
//        获取body
        final Map<String, Object> body = this.getBody(data);

//		远程调用
        JSONObject bodyjson=new JSONObject(body);
        final JSONObject retjson = RestServiceUtils.post(url, head, bodyjson);

//		处理服务返回
        if (!retjson.containsKey("code"))
            throw new Exception("返回数据错误,无[code]!");
        final Integer code = retjson.getInteger("code");
        final String message = retjson.getString("message");
        if(code!=0){
            String msg=String.format("返回报错,code:[%s],msg[%s]",code,message);
            throw new Exception(msg);
        }
        return retjson;
    }

    /**
     * 构造head head中包含token或签名sign
     * @param param 接口参数(接口参数(clientId,accessKey,loginUser))
     * @return http head
     */
    private Map<String,Object> getToken(Map<String, Object> param) throws Exception {
        final Object clientId = param.get("clientId");
        final Object accessKey = param.get("accessKey");
        final Object loginUser = param.get("loginUser");
        ExceptionUtils.checkBlankOrUndefined(clientId,"clientId不能为空");
        ExceptionUtils.checkBlankOrUndefined(accessKey,"accessKey不能为空");
        ExceptionUtils.checkBlankOrUndefined(loginUser,"loginUser");

        final int timestamp = Math.round(new Date().getTime() / 1000);
        final String plainText = loginUser.toString() + accessKey.toString() + String.valueOf(timestamp);
        final String loginToken= DigestUtil.md5Hex(plainText).toUpperCase();

        Map<String,Object> retmap=new LinkedHashMap<>();
        retmap.put("clientId",clientId);
//        retmap.put("accessKey",accessKey);
        retmap.put("loginUser",loginUser);
        retmap.put("loginToken",loginToken);
        retmap.put("timestamp",timestamp);
        return retmap;
    }

    /**
     * 将数据按照Body格式进行封装
     * @param data 数据
     * @return body map
     */
    private Map<String,Object> getBody(Map<String,Object> data){
        Map<String,Object> body=new LinkedHashMap<>();
        body.put("dto", data);
        return body;
    }

    /**
     * 查询接口封装
     * @param url        调用地址
     * @param param     接口参数(clientId,accessKey,loginUser)
     * @param query        查询条件JSON
     * @return 查询结果数据
     */
    @ServiceLog("查询服务")
    public List<Map<String, Object>> query(String url, Map<String,Object> param, Map<String, Object> query) throws Exception {
        List<Map<String,Object>> retlist=new ArrayList<Map<String,Object>>();
//		调用接口获取JSON
        JSONObject json=this.restInvoke(url,param,query);
//		处理返回值
        final JSONObject retdata = json.getJSONObject("data");
        final JSONArray retrows = retdata.getJSONArray("rows");
        for(Object data:retrows) {
            retlist.add((Map<String,Object>)data);
        }
        return retlist;
    }

    /**
     * 保存接口封装
     * @param datas 数据集合
     * @param param 接口参数
     * @param url 接口地址
     * @param entityInfo 实体信息
     */
    @ServiceLog("保存服务")
    public List<JSONObject> entitySave(List<Map<String, Object>> datas,Map<String, Object> param
            ,String url, JSONObject entityInfo) throws Exception {
        List<JSONObject> retlist = new ArrayList<JSONObject>();

        ExceptionUtils.checkBlankOrUndefined(param, "param");
        ExceptionUtils.checkBlankOrUndefined(url, "url为空");
        ExceptionUtils.checkBlankOrUndefined(entityInfo, "entityInfo为空");

//		过滤缓存
        final List<Map<String, Object>> filterList = entityCache.filterEntityChange(entityInfo, datas);

        for (Map<String,Object> data : filterList) {
//			循环单条处理
            try {
//				调用接口
                JSONObject retjson = this.restInvoke(url,param, data);
//				处理实体日志和缓存
                infoService.insertAitEntityInfo(entityInfo, data, null);
//				处理返回
                retlist.add(retjson);
            } catch (Exception ex) {
//				处理实体日志和缓存-失败信息
                infoService.insertAitEntityInfo(entityInfo, data, ex);
//				处理返回
                retlist.add(JSONResult.error(ex.getMessage()));
            }
        }
        return retlist;
    }

}
